﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenExpressApp.Command;
using OpenExpressApp.Module.WPF;
using OpenExpressApp.Editors;
using System.Collections;
using OpenExpressApp.MetaModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using OpenExpressApp.MetaModel.Audit;

namespace OpenExpressApp.WPF.Command
{
    /// <summary>
    /// 属性编辑器名利，传入参数为PropertyEditor
    /// </summary>
    public abstract class PropertyEditorCommand : CommandBase
    {
        public override bool CanVisible(object param)
        {
            return CanVisible(param as PropertyEditor);
        }
        public override bool CanExecute(object param)
        {
            return CanExecute(param as PropertyEditor);
        }
        public override void Execute(object param)
        {
            Execute(param as PropertyEditor);
        }

        public virtual bool CanVisible(PropertyEditor editor)
        {
            return true;
        }
        public virtual bool CanExecute(PropertyEditor editor)
        {
            return true;
        }
        public abstract void Execute(PropertyEditor editor);
    }

    public abstract class WPFViewCommand : CommandBase
    {
        public override bool CanVisible(object param)
        {
            return CanVisible(param as ObjectView);
        }
        public override bool CanExecute(object param)
        {
            return CanExecute(param as ObjectView);
        }
        public override void Execute(object param)
        {
            var view = param as ObjectView;
            try
            {
                this.Execute(view);
                if ((view is QueryObjectView) == false)
                {
                    this.LogSuccess(view);
                }
            }
            catch (Exception ex)
            {
                if ((view is QueryObjectView) == false)
                {
                    this.LogFailed(view, ex);
                }
                throw;
            }
        }

        public virtual bool CanVisible(ObjectView view)
        {
            return true;
        }
        public virtual bool CanExecute(ObjectView view)
        {
            return true;
        }
        public abstract void Execute(ObjectView view);

        #region 记录日志

        /// <summary>
        /// 记录日志
        /// </summary>
        /// <param name="view"></param>
        private void LogSuccess(ObjectView view)
        {
            string title = "执行命令完成：" + this.Label;
            string coderContent = string.Format(
@"类型名：{0}
命令ID：{1}", view.BOType.Name, this.Id);

            this.LogAsync(title, coderContent, view);
        }

        /// <summary>
        /// 记录执行错误的日志
        /// </summary>
        /// <param name="view"></param>
        /// <param name="ex"></param>
        private void LogFailed(ObjectView view, Exception ex)
        {
            string title = "执行命令失败：" + this.Label;
            string coderContent = string.Format(
@"类型名：{0}
命令ID：{1}
发生异常：{2}
堆栈:{3}", view.BOType.Name, this.Id, ex.Message, ex.StackTrace);

            this.LogAsync(title, coderContent, view);
        }

        private void LogAsync(string title, string coderContent, ObjectView view)
        {
            var entityInfo = ApplicationModel.GetBusinessObjectInfo(view.BOType);
            AuditLogService.LogAsync(new AuditLogItem()
            {
                Title = title,
                FriendlyContent = string.Format(@"对象：{0}", entityInfo.Label),
                CoderContent = coderContent,
                ModuleName = entityInfo.Module.Label,
                Type = AuditLogType.Command
            });
        }

        #endregion
    }

    public abstract class WPFListViewCommand : WPFViewCommand
    {
        public override bool CanVisible(ObjectView view)
        {
            return CanVisible(view as ListObjectView);
        }
        public override bool CanExecute(ObjectView view)
        {
            return CanExecute(view as ListObjectView);
        }
        public override void Execute(ObjectView view)
        {
            Execute(view as ListObjectView);
        }

        public virtual bool CanVisible(ListObjectView view)
        {
            return true;
        }
        public virtual bool CanExecute(ListObjectView view)
        {
            return true;
        }
        public abstract void Execute(ListObjectView view);

        /// <summary>
        /// 是否选择了一个和最一个对象同类型的对象
        /// 
        /// 未选择/选择的不一样，都返回false
        /// </summary>
        /// <param name="view"></param>
        /// <returns></returns>
        protected bool SelectedRightType(ListObjectView view)
        {
            if (view == null) throw new ArgumentNullException("view");

            var currentObject = view.CurrentObject;
            if (currentObject != null)
            {
                //如果选择了某一个对象，则这个对象，应该和view的对象类型相同。
                return currentObject.GetType() == view.BOType;
            }
            return false;
        }
        /// <summary>
        /// 已经选择某个对象
        /// </summary>
        /// <param name="view"></param>
        /// <returns></returns>
        protected bool Selected(ListObjectView view)
        {
            if (view == null) throw new ArgumentNullException("view");
            return view.CurrentObject != null;
        }
    }

    ///// <summary>
    ///// 生成窗体后根据View来自动调用的Command
    ///// </summary>
    //public abstract class WPFAutoCommand : WPFViewCommand { }

    /// <summary>
    /// 指定某类型的参数化Command
    /// </summary>
    /// <typeparam name="TParameter"></typeparam>
    public abstract class WPFParametrizedCommand<TParameter> : WPFViewCommand, IParametrizedCommand
        where TParameter : class, IQueryObject, new()
    {
        private IDetailObjectView _detailView;

        public WPFParametrizedCommand()
        {
            this._detailView = new DetailObjectView(typeof(TParameter));
            this._detailView.Data = new TParameter();
        }

        public TParameter Parameter
        {
            get
            {
                return this._detailView.CurrentObject as TParameter;
            }
        }

        #region IWPFControlGenerator Members

        public FrameworkElement CreateControl()
        {
            return this._detailView.Control as FrameworkElement;
        }

        object IControlGenerator.CreateControl()
        {
            return this.CreateControl();
        }

        #endregion

        #region IParametrizedCommand Members

        object IParametrizedCommand.Parameter
        {
            get
            {
                return this._detailView.CurrentObject;
            }
        }

        #endregion
    }

    public abstract class TextBoxCommand : WPFViewCommand, IParametrizedCommand
    {
        private FrameworkElement _control;

        private TextBox _textBox;

        public string Parameter
        {
            get
            {
                if (this._textBox == null)
                {
                    return string.Empty;
                }
                return this._textBox.Text;
            }
        }

        public FrameworkElement CreateControl()
        {
            if (this._control == null)
            {
                var panel = new WrapPanel();

                this._textBox = new TextBox()
                {
                    BorderBrush = Brushes.Black,
                    Name = this.ProgramingName,
                    Width = 150,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(2)
                };

                panel.Children.Add(this._textBox);

                this._control = panel;
            }
            return this._control;
        }

        #region IParametrizedCommand Members

        object IParametrizedCommand.Parameter
        {
            get
            {
                return this.Parameter;
            }
        }

        object IControlGenerator.CreateControl()
        {
            return this.CreateControl();
        }

        #endregion
    }
}